package com.bupt.uchouten.common.linkage;

import com.bupt.uchouten.common.block.entity.TenkaiVigorousVineBlockEntity;
import com.bupt.uchouten.common.register.UchoutenSounds;
import com.pixelmonmod.pixelmon.Pixelmon;
import com.pixelmonmod.pixelmon.api.events.HealerEvent;
import com.pixelmonmod.pixelmon.api.pokemon.Pokemon;
import com.pixelmonmod.pixelmon.api.pokemon.item.pokeball.PokeBall;
import com.pixelmonmod.pixelmon.api.pokemon.item.pokeball.PokeBallRegistry;
import com.pixelmonmod.pixelmon.api.storage.PlayerPartyStorage;
import com.pixelmonmod.pixelmon.api.storage.StorageProxy;
import com.pixelmonmod.pixelmon.comm.ChatHandler;
import com.pixelmonmod.pixelmon.comm.packetHandlers.OpenScreenPacket;
import com.pixelmonmod.pixelmon.enums.EnumGuiScreen;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class TenkaiVVInnerPixelmonBlockEntity {

    private boolean beingUsed;
    private PlayerPartyStorage storage;
    private Player player;
    private int tickCount;

    public float rotation = 0.0F;
    public int flashTimer = 0;
    private boolean allPlaced;
    private int pokemonLastPlaced;

    public PokeBall[] pokeballType = new PokeBall[6];
    private boolean stayLight;
    private boolean playSound;

    public TenkaiVVInnerPixelmonBlockEntity() {
    }

    public boolean isBeingUsed() {
        return this.beingUsed;
    }

    public boolean isStayLight() {
        return this.stayLight;
    }

    public boolean isAllPlaced() {
        return this.allPlaced;
    }

    public void setRotation(float rotation) {
        this.rotation = rotation;
    }

    public PokeBall[] getPokeballType() {
        return pokeballType;
    }

    public InteractionResult use(TenkaiVigorousVineBlockEntity blockEntity, Player player) {
        if (this.beingUsed) {
            ChatHandler.sendChat(player, "pixelmon.blocks.healer");
            return InteractionResult.FAIL;
        } else {
            boolean post = Pixelmon.EVENT_BUS.post(new HealerEvent.Pre(player, blockEntity.getBlockPos(), false));
            if (post) {
                return InteractionResult.FAIL;
            } else {
                startHealing(player);
                return InteractionResult.CONSUME;
            }
        }
    }

    private void startHealing(Player player) {
        Optional.ofNullable(StorageProxy.getPartyNow((ServerPlayer) player)).ifPresent(storage -> {
            this.storage = storage;
            this.storage.teleportPos.store(player.getCommandSenderWorld().dimension(), player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
        });
        this.player = player;
        this.beingUsed = true;
        OpenScreenPacket.open(player, EnumGuiScreen.Healer);

        this.tickCount = 0;
        this.allPlaced = false;
        this.pokemonLastPlaced = -1;

        Arrays.fill(this.pokeballType, null);

        this.stayLight = false;
    }

    private void refreshTexture(TenkaiVigorousVineBlockEntity blockEntity) {
        if (Optional.ofNullable(blockEntity.getLevel()).isPresent() && !blockEntity.getLevel().isClientSide) {
            ((ServerLevel) blockEntity.getLevel()).getChunkSource().blockChanged(blockEntity.getBlockPos());
            blockEntity.setChanged();
        }
    }

    private int getTicksToHeal() {
        return 60;
    }

    public void getUpdateTag(CompoundTag nbt) {
        for(int i = 0; i < this.pokeballType.length; ++i) {
            if (this.pokeballType[i] != null) {
                nbt.putString("PokeballType" + i, this.pokeballType[i].getName());
            }
        }

        nbt.putBoolean("BeingUsed", this.beingUsed);
        nbt.putBoolean("AllPlaced", this.allPlaced);
        nbt.putBoolean("StayLight", this.stayLight);
    }

    public void onDataPacket(CompoundTag compound) {
        for(int i = 0; i < this.pokeballType.length; ++i) {
            this.pokeballType[i] = null;
            if (compound.contains("PokeballType" + i)) {
                this.pokeballType[i] = PokeBallRegistry.getPokeBall(compound.getString("PokeballType" + i)).orElse((PokeBall)null);
            }
        }

        if (compound.contains("BeingUsed")) {
            this.beingUsed = compound.getBoolean("BeingUsed");
            this.allPlaced = compound.getBoolean("AllPlaced");
            this.stayLight = compound.getBoolean("StayLight");
        }
    }


    public void tick(Level level, BlockPos blockPos, BlockState state, TenkaiVigorousVineBlockEntity blockEntity) {
        if (level.isClientSide) {
            this.rotation += 19.0F;
            ++this.flashTimer;
        } else {
            if (this.beingUsed) {
                if (this.allPlaced && !this.playSound) {
                    level.playSound(null, blockEntity.getBlockPos(), UchoutenSounds.TENKAI_VIGOROUS_VINE_HEALING, SoundSource.BLOCKS, 0.7F, 1.0F);
                    this.playSound = true;
                }

                ++this.tickCount;
                if (!this.allPlaced && this.tickCount == 5) {
                    boolean hasNextPokemon = false;
                    this.storage.retrieveAll("BlockInteract");

                    List<Pokemon> team = this.storage.getTeam();
                    for (int i = this.pokemonLastPlaced + 1; i < team.size(); ++i) {
                        if (Optional.ofNullable(team.get(i)).isPresent()) {
                            this.pokemonLastPlaced = i;
                            hasNextPokemon = true;
                            this.pokeballType[i] = team.get(i).getBall();
                            break;
                        }
                    }

                    if (!hasNextPokemon) {
                        this.allPlaced = true;
                    }

                    this.tickCount = 0;
                    this.refreshTexture(blockEntity);
                }

                int ticksToHeal = this.getTicksToHeal();
                if (this.tickCount == ticksToHeal - 30) {
                    this.stayLight = true;
                    this.refreshTexture(blockEntity);
                }

                if (this.tickCount == ticksToHeal) {
                    this.storage.getTeam().forEach(Pokemon::heal);
                    this.beingUsed = false;
                    this.playSound = false;
                    this.refreshTexture(blockEntity);
                    this.player.closeContainer();
                }

                level.sendBlockUpdated(blockEntity.getBlockPos(), state, state, 3);
            }

        }
    }
}
